package com.hw.springcloud.lb;

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Classname: LoadBalancerImpl
 * @Description: 轮询算法实现类(使用 @Component注解 将这个类注入到spring容器中)
 * @Date: 2021/8/13
 * @Author: huwei
 */
@Component
public class LoadBalancerImpl implements LoadBalancer {

    /**
     * 初始化一个原子类(初始值设置为0),用原子类操作更加安全
     */
    private final AtomicInteger atomicInteger = new AtomicInteger(0);

    /**
     * 轮询次数计算
     * @return 次数
     */
    public final int getAndIncrement() {
        // 当前值
        int current;
        // 访问次数
        int next;
        // 自旋锁[atomicInteger.compareAndSet(current,next)方法,
        // 将current和atomicInteger的值对比(atomicInteger的值在内存中),如果相等就把值改为next返回true,如果不相等就返回false]
        // 如果修改了就返回true,但是在while中会取反就是false,终止do循环,返回next
        // 防止在高并发的情况下有线程改变了数字而不知道,使用自旋锁保证数据的真实性
        do {
            // current 的值就是原子类的值
            current = this.atomicInteger.get();
            // next的值就是current+1的值,但是不能超过Integer的最大值,否则就重0开始
            next = current >= Integer.MAX_VALUE ? 0 : current + 1;
        } while (!this.atomicInteger.compareAndSet(current,next));
        return next;
    }

    @Override
    public ServiceInstance serviceInstance(List<ServiceInstance> serviceInstanceList) {
        // 通过方法返回次数对服务集合取余数,通过余数获得服务集合的下标,进而获得服务实例
        int index =  getAndIncrement() % serviceInstanceList.size();
        return serviceInstanceList.get(index);
    }

}
